﻿/***************************************************
//  Copyright (c) Premium Tax Free 2011
/***************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using RibbonLib;
using RibbonLib.Controls;
using RibbonLib.Controls.Events;
using RibbonLib.Interop;
using PremierTaxFree.Scan;
using PremierTaxFree.Tools;
using PremierTaxFree.PTFLib.Extensions;
using PremierTaxFree.PTFLib.Security;
using PremierTaxFree.Properties;
using PremierTaxFree.PTFLib.Data;

using RLTab = RibbonLib.Controls.RibbonTab;
using RLButton = RibbonLib.Controls.RibbonButton;

namespace PremierTaxFree
{
    public partial class ScanForm : Form, IMessageFilter
    {
        #region Private members

        private const uint BRUSH_CMD_ID = 2000, TOOLS_CMD_ID = 2050, SIZE_CMD_ID = 0;

        private RLTab m_tabMain;
        private RibbonGroup m_groupMain;
        private RibbonTabGroup m_tabGroupDesign;
        private RLTab m_tabEdit;
        private RLTab m_tabGroupInfo;
        private RibbonGroup m_groupDesign;
        private RibbonGroup m_groupExport;

        private RLButton m_buttonSelectDesign;
        private RLButton m_buttonHome;

        private RLButton m_buttonSelect2;
        private RLButton m_buttonResize;
        private RLButton m_buttonRotate;
        private RLButton m_buttonScissors;

        private RLButton m_buttonNew2;
        private RLButton m_buttonOpen2;
        private RLButton m_buttonSave2;
        private RLButton m_buttonSaveAs2;
        private RLButton m_buttonExport;
        private RLButton m_buttonExit;
        private RLButton m_buttonScan;

        private RibbonContextMenuStrip m_ribbonContextMenuStrip;

        private RibbonDropDownGallery m_gallerySize;
        private RibbonSplitButtonGallery m_galleryBrushes;
        private RibbonSplitButtonGallery m_galleryTools;
        private RibbonInRibbonGallery m_galleryShapes;

        private RLButton[] m_buttonsBrushes, m_buttonsTools;

        private string m_FileName;

        //Scan
        private bool m_msgfilter;
        private Twain m_tw;
        private int m_picnumber = 0;

        #endregion

        #region Constructor

        public ScanForm()
        {
            InitializeComponent();

            border.Paint += (o, e) =>
            {
                var r1 = this.ClientRectangle;
                var r2 = r1;
                var r3 = r1;
                var r4 = r1;

                r2.Inflate(-3, -3);
                r3.Inflate(-6, -6);
                r4.Inflate(-9, -9);

                e.Graphics.DrawRectangles(SystemPens.ActiveBorder, new Rectangle[] { r1, r2, r3, r4 });
            };

            m_tabMain = new RLTab(ribbon1, (uint)eRibbonMarkupCommands.cmdTabHome);
            m_groupMain = new RibbonGroup(ribbon1, (uint)eRibbonMarkupCommands.cmdGroupMain);
            m_tabGroupDesign = new RibbonTabGroup(ribbon1, (uint)eRibbonMarkupCommands.cmdTabGroupDesign);
            m_tabEdit = new RLTab(ribbon1, (uint)eRibbonMarkupCommands.cmdTabEdit);
            m_tabGroupInfo = new RLTab(ribbon1, (uint)eRibbonMarkupCommands.cmdGroupInfo);
            m_groupDesign = new RibbonGroup(ribbon1, (uint)eRibbonMarkupCommands.cmdGroupDesign);
            m_groupExport = new RibbonGroup(ribbon1, (uint)eRibbonMarkupCommands.cmdGroupExport);
            m_buttonSelectDesign = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonSelectDesign);
            m_buttonSelectDesign.ExecuteEvent += new EventHandler<ExecuteEventArgs>(ButtonSelectDesign_ExecuteEvent);
            m_buttonHome = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonHome);
            m_buttonHome.ExecuteEvent += new EventHandler<ExecuteEventArgs>(ButtonHome_ExecuteEvent);

            m_buttonSelect2 = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonSelect);
            m_buttonResize = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonResize);
            m_buttonRotate = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonRotate);
            m_buttonScissors = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonScissors);
            m_buttonScissors.ExecuteEvent += new EventHandler<ExecuteEventArgs>(EditButtonCommand_ExecuteEvent);

            m_buttonNew2 = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonNew);
            m_buttonNew2.ExecuteEvent += new EventHandler<ExecuteEventArgs>(CommandButtonCommand_ExecuteEvent);
            m_buttonOpen2 = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonOpen);
            m_buttonOpen2.ExecuteEvent += new EventHandler<ExecuteEventArgs>(CommandButtonCommand_ExecuteEvent);
            m_buttonSave2 = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonSave);
            m_buttonSave2.ExecuteEvent += new EventHandler<ExecuteEventArgs>(CommandButtonCommand_ExecuteEvent);
            m_buttonSaveAs2 = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonSaveAs);
            m_buttonSaveAs2.ExecuteEvent += new EventHandler<ExecuteEventArgs>(CommandButtonCommand_ExecuteEvent);
            m_buttonExport = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonExport);
            m_buttonExport.ExecuteEvent += new EventHandler<ExecuteEventArgs>(CommandButtonCommand_ExecuteEvent);
            m_buttonExit = new RLButton(ribbon1, (int)eRibbonMarkupCommands.cmdButtonExit);
            m_buttonExit.ExecuteEvent += new EventHandler<ExecuteEventArgs>(CommandButtonCommand_ExecuteEvent);
            m_buttonScan = new RLButton(ribbon1, (uint)eRibbonMarkupCommands.cmdButtonScan);
            m_buttonScan.ExecuteEvent += new EventHandler<ExecuteEventArgs>(CommandButtonCommand_ExecuteEvent);

            m_ribbonContextMenuStrip = new RibbonContextMenuStrip(ribbon1, (uint)eRibbonMarkupCommands.cmdContextMap);

            this.MouseClick += new MouseEventHandler(Form_MouseClick);

            this.ContextMenuStrip = m_ribbonContextMenuStrip;

            m_galleryTools = new RibbonSplitButtonGallery(ribbon1, (uint)eRibbonMarkupCommands.cmdGalleryTools);
            m_gallerySize = new RibbonDropDownGallery(ribbon1, (uint)eRibbonMarkupCommands.cmdGallerySize);
            m_galleryBrushes = new RibbonSplitButtonGallery(ribbon1, (uint)eRibbonMarkupCommands.cmdGalleryBrushes);
            m_galleryShapes = new RibbonInRibbonGallery(ribbon1, (uint)eRibbonMarkupCommands.cmdGalleryShapes);

            m_gallerySize.PreviewEvent += new EventHandler<ExecuteEventArgs>(DropDownGallery_OnPreview);
            m_gallerySize.CancelPreviewEvent += new EventHandler<ExecuteEventArgs>(DropDownGallery_OnCancelPreview);
            m_gallerySize.ItemsSourceReady += new EventHandler<EventArgs>(SplitButtonGallery_ItemsSourceReady);
            m_gallerySize.ExecuteEvent += new EventHandler<ExecuteEventArgs>(SplitButtonGallery_ExecuteEvent);

            m_galleryBrushes.CategoriesReady += new EventHandler<EventArgs>(SplitButtonGallery_CategoriesReady);
            m_galleryBrushes.ItemsSourceReady += new EventHandler<EventArgs>(SplitButtonGallery_ItemsSourceReady);
            m_galleryBrushes.ExecuteEvent += new EventHandler<ExecuteEventArgs>(SplitButtonGallery_ExecuteEvent);

            m_galleryShapes.ItemsSourceReady += new EventHandler<EventArgs>(SplitButtonGallery_ItemsSourceReady);
            m_galleryShapes.ExecuteEvent += new EventHandler<ExecuteEventArgs>(SplitButtonGallery_ExecuteEvent);

            m_galleryTools.ItemsSourceReady += new EventHandler<EventArgs>(SplitButtonGallery_ItemsSourceReady);
            m_galleryTools.ExecuteEvent += new EventHandler<ExecuteEventArgs>(SplitButtonGallery_ExecuteEvent);

            Canvas.MouseMove += (o, e) =>
            {
                Point p = Canvas.PointToClient(Control.MousePosition);
                tssl3.Text = p.X.ToString();
                tssl5.Text = p.Y.ToString();
            };

            BaseTool.Info += (o, e) =>
            {
                tssl6.Text = e.Name;
                tssl7.Text = e.Value;
            };

            BaseTool.Reset(Canvas);

            m_tw = new Twain();
            m_tw.Init(this.Handle);
        }

        #endregion

        #region RIBBON HANDLERS

        private void SplitButtonGallery_ItemsSourceReady(object sender, EventArgs e)
        {
            if (sender == m_galleryTools)
            {
                List<RLButton> list = new List<RLButton>();

                uint i = 0;
                foreach (var image in imageListTools.Images)
                {
                    RLButton btn = new RLButton(ribbon1, TOOLS_CMD_ID + i)
                    {
                        Label = "Tool: " + i++,
                        LargeImage = ribbon1.ConvertToUIImage((Bitmap)image),
                    };
                    btn.ExecuteEvent += new EventHandler<ExecuteEventArgs>(GalleryButton_ExecuteEvent);
                    list.Add(btn);
                }

                m_buttonsTools = list.ToArray();

                IUICollection itemsSource = m_galleryTools.ItemsSource;
                itemsSource.Clear();
                i = 0;

                foreach (var image in imageListTools.Images)
                {
                    itemsSource.Add(new GalleryCommandPropertySet()
                    {
                        CategoryID = 1,
                        CommandID = TOOLS_CMD_ID + i++,
                        CommandType = CommandType.Action,
                    });
                }
            }      
            else if (sender == m_gallerySize)
            {
                IUICollection itemsSource = m_gallerySize.ItemsSource;
                itemsSource.Clear();
                foreach (Image image in imageListLines.Images)
                {
                    itemsSource.Add(new GalleryItemPropertySet()
                    {
                        ItemImage = ribbon1.ConvertToUIImage((Bitmap)image),
                    });
                }                
            }
            else if (sender == m_galleryBrushes)
            {
                // set label
                m_galleryBrushes.Label = "Brushes";

                // prepare helper classes for commands
                List<RLButton> list = new List<RLButton>();

                uint i = 0;
                foreach (var image in imageListBrushes.Images)
                {
                    RLButton btn = new RLButton(ribbon1, BRUSH_CMD_ID + i)
                    {
                        Label = "Brush: " + i++,
                        LargeImage = ribbon1.ConvertToUIImage((Bitmap)image),
                    };
                    btn.ExecuteEvent += new EventHandler<ExecuteEventArgs>(GalleryButton_ExecuteEvent);
                    list.Add(btn);
                }

                m_buttonsBrushes = list.ToArray();

                // set _splitButtonGallery items
                IUICollection itemsSource = m_galleryBrushes.ItemsSource;
                itemsSource.Clear();
                i = 0;
                foreach (Image image in imageListBrushes.Images)
                {
                    itemsSource.Add(new GalleryCommandPropertySet()
                    {
                        CategoryID = 1,
                        CommandID = BRUSH_CMD_ID + i++,
                        CommandType = CommandType.Action,
                    });
                }
            }
            else if (sender == m_galleryShapes)
            {
                // set _inRibbonGallery items
                IUICollection itemsSource = m_galleryShapes.ItemsSource;
                itemsSource.Clear();
                foreach (Image image in imageListShapes.Images)
                {
                    itemsSource.Add(new GalleryItemPropertySet()
                    {
                        ItemImage = ribbon1.ConvertToUIImage((Bitmap)image)
                    });
                }
            }                  
            else
                throw new NotImplementedException();
        }

        private void SplitButtonGallery_ExecuteEvent(object sender, ExecuteEventArgs e)
        {
            Debug.WriteLine(e.CurrentValue.PropVariant.Value.ToString());
            BaseTool.FireExecute(Canvas, sender, e);

            if (sender == m_galleryShapes)
            {
            }
            else if (sender == m_galleryBrushes)
            {
            }
            else if (sender == m_galleryTools)
            {
            }
            else if (sender == m_gallerySize)
            {
                RibbonDropDownGallery gal = (RibbonDropDownGallery)sender;
                Canvas.LineSize = LineSize[Convert.ToInt32(gal.SelectedItem)];
            }
            else
                throw new NotImplementedException();
        }

        readonly int[] LineSize = { 1, 2, 5, 10, 15, 20, 25, 30, 40, 50, 100 };

        private void GalleryButton_ExecuteEvent(object sender, ExecuteEventArgs e)
        {
            RLButton rb = (RLButton)sender;

            if (((eBrushes)rb.CommandID).InRange(eBrushes.Brush1, eBrushes.Brush9))
            {
                Canvas.BrushNum = Convert.ToInt32(rb.CommandID - BRUSH_CMD_ID);
            }
            else if (((eTools)rb.CommandID).InRange(eTools.ToolMin, eTools.ToolMax))
            {
                switch ((eTools)rb.CommandID)
                {
                    case eTools.Scissors:
                        BaseTool.Reset(Canvas);
                        break;
                    case eTools.Pen:
                        BaseTool.Install(new PenTool(Canvas));
                        break;
                    case eTools.PenPolio:
                        BaseTool.Install(new PolyPenTool(Canvas));
                        break;
                    case eTools.Eraser:
                        BaseTool.Install(new EraserTool(Canvas));
                        break;
                }                    
            }            
        }

        private void EditButtonCommand_ExecuteEvent(object sender, ExecuteEventArgs e)
        {
            if (sender == m_buttonScissors)
            {
                //BaseTool.Install(new CropTool(Canvas));
            }
            else
                throw new NotImplementedException();
        }

        private void CommandButtonCommand_ExecuteEvent(object sender, ExecuteEventArgs e)
        {
            if (sender == m_buttonScan)
            {
                if (!m_msgfilter)
                {
                    this.Enabled = false;
                    m_msgfilter = true;
                    Application.AddMessageFilter(this);
                }
                m_tw.Select();
                m_tw.Acquire();
            }
            else if (sender == m_buttonNew2)
            {
                ScanForm form = new ScanForm();
                form.Show();
            }
            else if (sender == m_buttonOpen2)
            {
                using (OpenFileDialog dlg = new OpenFileDialog())
                {
                    dlg.Multiselect = false;
                    dlg.Filter = "BMP|*.bmp|JPG|*.jpg|PNG|*.png|All|*.*";
                    dlg.CheckFileExists = true;

                    if (dlg.ShowDialog(this) == DialogResult.OK)
                    {
                        Canvas.BackgroundImage = Image.FromFile(dlg.FileName);
                        Canvas.Invalidate();
                    }
                }
            }
            else if (sender == m_buttonSave2)
            {
                if (!string.IsNullOrEmpty(m_FileName))
                {
                    using (Bitmap bmp = new Bitmap(Canvas.Width, Canvas.Height))
                    {
                        Canvas.DrawToBitmap(bmp, Canvas.ClientRectangle);
                        bmp.Save(m_FileName);
                    }
                }
            }
            else if (sender == m_buttonSaveAs2) //SaveAs
            {
                using (SaveFileDialog dlg = new SaveFileDialog())
                {
                    dlg.Filter = "JPG|*.jpg";
                    dlg.CheckPathExists = true;
                    dlg.AddExtension = true;

                    if (dlg.ShowDialog(this) == DialogResult.OK)
                    {
                        m_FileName = dlg.FileName;

                        using (Bitmap bmp = new Bitmap(Canvas.Width, Canvas.Height))
                        {
                            Canvas.DrawToBitmap(bmp, Canvas.ClientRectangle);
                            bmp.Save(m_FileName);
                        }
                    }
                }
            }
            else if (sender == m_buttonExport)
            {
                string name = "".Random(10);
                IDictionary dict = new Hashtable();
                dict.Add("FileName", name);
                dict.Add("CountryCode", "".Random(10));
                dict.Add("Business", 20);
                dict.Add("RetailerID", "".Random(20));
                dict.Add("VoucherID", "".Random(20));
                dict.Add("SiteID", "".Random(20));
                dict.Add("VoucherImage", Resources.blue.ToArray());
                dict.Add("BarCodeImage", Resources.red.ToArray());
                dict.Add("DateInserted", DateTime.Now);
                ProtectedXml xml = new ProtectedXml(ProtectionOptions.SignAndEncript);
                xml.AddElement("voucher", dict);
                DataAccess.InsertFileAsync_Client(name, xml.OuterXml);
            }
            else if (sender == m_buttonExit)
            {
                Close();
            }
            else if (sender == m_buttonExit) //Exit
            {
                Application.Exit();
            }
            else
                throw new NotImplementedException();
        }

        private void ButtonSelectDesign_ExecuteEvent(object sender, ExecuteEventArgs e)
        {
            m_tabGroupDesign.ContextAvailable = ContextAvailability.Active;
        }

        private void ButtonHome_ExecuteEvent(object sender, ExecuteEventArgs e)
        {
            m_tabGroupDesign.ContextAvailable = ContextAvailability.NotAvailable;
        }

        private void Form_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Point p = PointToScreen(e.Location);
                ribbon1.ShowContextPopup((uint)eRibbonMarkupCommands.cmdContextMap, p.X, p.Y);
            }
        }

        private void SplitButtonGallery_CategoriesReady(object sender, EventArgs e)
        {
            // set _splitButtonGallery categories
            IUICollection categories = m_galleryBrushes.Categories;
            categories.Clear();
            categories.Add(new GalleryItemPropertySet() { Label = "Brushes", CategoryID = 1 });
        }

        private void DropDownGallery_OnCancelPreview(object sender, ExecuteEventArgs e)
        {
            Debug.WriteLine("DropDownGallery::OnCancelPreview");
        }

        private void DropDownGallery_OnPreview(object sender, ExecuteEventArgs e)
        {
            Debug.WriteLine("DropDownGallery::OnPreview");
        }

        #endregion

        #region Overloads

        private const int POINTS_TO_STEP = 5;

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                Canvas.DeleteSelectedImages();                
            }
            else if (e.Control && e.KeyCode == Keys.C)
            {
                IDataObject data = new DataObject();
                data.SetData(Canvas.m_SelectedImgList.GetType().FullName, Canvas.m_SelectedImgList);
                Clipboard.SetDataObject(data, true);

                foreach (var obj in Canvas.m_SelectedImgList)
                    Canvas.Invalidate(obj.Rect.InflateEx());
                Canvas.m_SelectedImgList.Clear();
            }
            else if (e.Control && e.KeyCode == Keys.V)
            {
                if (Clipboard.ContainsData(Canvas.m_SelectedImgList.GetType().FullName))
                {
                    HashSet<ImageObj> hashSet = (HashSet<ImageObj>)
                        Clipboard.GetData(Canvas.m_SelectedImgList.GetType().FullName);

                    foreach (var obj in hashSet)
                    {
                        obj.MoveTo(0, 0);
                        Canvas.m_ImgList.Add(obj);
                        Canvas.Invalidate(obj.Rect.InflateEx());
                    }
                    Canvas.m_SelectedImgList.Clear();
                }
            }
            else if (e.Control && e.KeyCode == Keys.X)
            {
                IDataObject data = new DataObject();
                data.SetData(Canvas.m_SelectedImgList.GetType().FullName, Canvas.m_SelectedImgList);
                Clipboard.SetDataObject(data, true);

                foreach (var obj in Canvas.m_SelectedImgList)
                {
                    Canvas.m_ImgList.Remove(obj);
                    Canvas.Invalidate(obj.Rect.InflateEx());
                }
                Canvas.m_SelectedImgList.Clear();
            }
            else if (e.Control && e.KeyCode == Keys.Y)
            {
                //m_UndoRedoManager.Redo();
            }
            else if (e.Control && e.KeyCode == Keys.Z)
            {
                //m_UndoRedoManager.Undo();
            }
            else if (!Canvas.m_SelectedImgList.IsEmpty())
            {
                foreach (var obj in Canvas.m_SelectedImgList)
                {
                    if (e.KeyCode == Keys.Left)
                    {
                        obj.Move(-POINTS_TO_STEP, 0);
                    }
                    else if (e.KeyCode == Keys.Right)
                    {
                        obj.Move(POINTS_TO_STEP, 0);
                    }
                    else if (e.KeyCode == Keys.Up)
                    {
                        obj.Move(0, -POINTS_TO_STEP);
                    }
                    else if (e.KeyCode == Keys.Down)
                    {
                        obj.Move(0, POINTS_TO_STEP);
                    }

                    Invalidate(obj.Rect.InflateEx());
                }
            }

            base.OnKeyDown(e);
        }

        #endregion

        #region Menus

        private void tcxMenu_Opening(object sender, CancelEventArgs e)
        {
            Canvas.m_SelectedImgList.Clear();

            Point point = Canvas.PointToClient(Control.MousePosition);

            foreach (var obj in Canvas.m_ImgList)
            {
                if (obj.Rect.Contains(point))
                {
                    Canvas.m_SelectedImgList.Add(obj);
                    obj.Click(point);
                    break;
                }
            }

            e.Cancel = Canvas.m_SelectedImgList.IsEmpty();
            Canvas.Invalidate();            
        }

        #endregion

        bool IMessageFilter.PreFilterMessage(ref Message m)
        {
            TwainCommand cmd = m_tw.PassMessage(ref m);
            if (cmd == TwainCommand.Not)
                return false;

            switch (cmd)
            {
                case TwainCommand.CloseRequest:
                    {
                        StopScan();
                        m_tw.CloseSrc();
                        break;
                    }
                case TwainCommand.CloseOk:
                    {
                        StopScan();
                        m_tw.CloseSrc();
                        break;
                    }
                case TwainCommand.DeviceEvent:
                    {
                        break;
                    }
                case TwainCommand.TransferReady:
                    {
                        ArrayList pics = m_tw.TransferPictures();
                        StopScan();
                        m_tw.CloseSrc();
                        m_picnumber++;

                        for (int i = 0; i < pics.Count; i++)
                        {
                            Debug.Assert(i == 0, "TODO");
                            IntPtr img = (IntPtr)pics[i];
                            Canvas.Update(img);
                            //PicForm newpic = new PicForm(img);
                            //newpic.MdiParent = this;
                            //int picnum = i + 1;
                            //newpic.Text = "ScanPass" + picnumber + "_Pic" + picnum;
                            //newpic.Show();
                        }
                        break;
                    }
                default:
                    {
                        //Debugger.Break();
                        //Debug.WriteLine(cmd.ToString());
                        break;
                    }
            }

            return true;
        }

        private void StopScan()
        {
            if (m_msgfilter)
            {
                Application.RemoveMessageFilter(this);
                m_msgfilter = false;
                this.Enabled = true;
                this.Activate();
            }
        }
    }   
}
